package reentrant;

import lombok.extern.slf4j.Slf4j;

/*可重入：线程，执行外层方法已经获取了锁；在方法中可以再次获取该锁。
、、、、、如果一个线程持有某个管程对象上的锁，那么它就有权访问所有在该管程对象上同步的块。这就叫可重入。
、、、、、若线程已经持有锁，那么它就可以重复访问所有使用该锁的代码块。
 */
@Slf4j
public class CanReentrantLock {
    private boolean isLocked = false;
    private Thread lockedBy = null;//保存已经获得锁的线程。
    int lockedCount = 0;//记录同一个线程重复对一个锁对象加锁的次数。

    public synchronized void lock() throws InterruptedException {
        Thread callingThread = Thread.currentThread();
        while (isLocked && lockedBy != callingThread) { //不用if，而用 while，是为了防止假唤醒
            wait(); //使当前线程阻塞
        }
        isLocked = true;
        lockedCount++;
        lockedBy = callingThread;
        log.info("lockedCount:" + lockedCount);
    }

    public synchronized void unlock() {
        if (Thread.currentThread() == this.lockedBy) {
            lockedCount--;
            if (lockedCount == 0) {
                isLocked = false;
                notify(); //唤醒一个处于等待状态的线程
            }
        }
    }
}
